# -*- coding: utf-8 -*-
from django.template.loader import get_template
from django.template import Template, Context
from django.shortcuts import render
from django.http import HttpResponse
import django.forms
import pdb
import datetime

from safeinside.path import MSLib, config

MSLib.glogger.at(MSLib.Logs.OBJECTS).setlevel(MSLib.SimpleLogger.INFO)
MSLib.glogger.at(MSLib.Logs.OBJECTS).setident('objects')

MSLib.glogger.at(MSLib.Logs.MSDB).setlevel(MSLib.SimpleLogger.INFO)
MSLib.glogger.at(MSLib.Logs.MSDB).setident('msdb')

class ObjectsFilterForm(django.forms.Form):
    PCNIdMin = django.forms.IntegerField()
    PCNIdMax = django.forms.IntegerField()
class MacFilterForm(django.forms.Form):
    filterMAC = django.forms.CharField()
    
class ObjectCreateForm(django.forms.Form):
    objMac = django.forms.CharField()
    objPCNId = django.forms.IntegerField()
    regions = \
    [
     ('dev', 'Санкт-Петербург'),
     ('car', 'Республика Карелия'),
    ]
    versions = \
    [
     ('', 'оставить прошивку по-умолчанию'),
     ('CID_1240argus_TX9.bin', 'CID_1240argus_TX9'),
     ('CID_1222A.bin', 'CID_1222A'),
     ('CID_1222.bin', 'CID_1222'),
    ]
    objNewFirmwareSelected = django.forms.ChoiceField(required=False, choices=versions, initial='')
    objNewFirmwareEntered = django.forms.CharField(required=False)
    objRegionSelected = django.forms.ChoiceField(choices=regions, initial='Санкт-Петербург')

class ObjectRenameForm(django.forms.Form):
    objOldPCNId = django.forms.IntegerField(widget=django.forms.NumberInput(attrs={'readonly':'readonly'}))
    objOldLogin = django.forms.CharField(widget=django.forms.TextInput(attrs={'readonly':'readonly'}))
    objNewPCNId = django.forms.IntegerField(required=False)
    objNewLogin = django.forms.CharField(required=False)
    
class ReloadFirmwareForm(django.forms.Form):
    objOldPCNId = django.forms.IntegerField(widget=django.forms.NumberInput(attrs={'readonly':'readonly'}))
    objOldLogin = django.forms.CharField(widget=django.forms.TextInput(attrs={'readonly':'readonly'}))
    objOldMSId = django.forms.IntegerField(widget=django.forms.NumberInput(attrs={'readonly':'readonly'}))
    objOldFirmware = django.forms.CharField(widget=django.forms.TextInput(attrs={'readonly':'readonly'}))
    versions = \
    [
     ('', 'введите имя файла'),
     ('CID_1240argus_TX9.bin', 'CID_1240argus_TX9'),
     ('CID_1222A.bin', 'CID_1222A'),
     ('CID_1222.bin', 'CID_1222'),
    ]
    objNewFirmwareSelected = django.forms.ChoiceField(choices=versions, initial='', required=False)
    objNewFirmwareEntered = django.forms.CharField(required=False)


dbconfig = \
{
 'host': config.get('msdb', 'host'),
 'port': config.get('msdb', 'port'),
 'dbname' : config.get('msdb', 'dbname'),
 'user': config.get('msdb', 'user'),
 'password': config.get('msdb', 'pwd'),
}

def hello(request):
    return render(request, 'safeinside/hello.html', {})
    
def getObjects(request, mode, params):
    params['filter_objects'] = ObjectsFilterForm(request.POST)
    params['filter_mac'] = MacFilterForm(request.POST)
    params['request_path'] = str(request.path)

    all = MSLib.Objects()
    MSLib.CarOnlineDB(dbconfig).objectsLoad(all, ['dev', 'del', 'car'])
    all.filter(config.get('main', 'normal_objects'))
    params['objs_all'] = all
    params['mode'] = mode
    
    objs = []
    if mode == 'all':
        for o in all.all():
            if params['filter_objects'].is_valid():
                data = params['filter_objects'].cleaned_data
                if data['PCNIdMin'] < o.targetid and data['PCNIdMax'] > o.targetid:
                    objs.append(o)
            elif params['filter_mac'].is_valid():
                data = params['filter_mac'].cleaned_data
                if o.caronline_macid.find(data['filterMAC']) != -1:
                    objs.append(o)
            else:
                objs.append(o)
                
    elif mode == 'enabled':
        for o in all.enabled():
            if params['filter_objects'].is_valid():
                data = params['filter_objects'].cleaned_data
                if data['PCNIdMin'] < o.targetid and data['PCNIdMax'] > o.targetid:
                    objs.append(o)
            elif params['filter_mac'].is_valid():
                data = params['filter_mac'].cleaned_data
                if o.caronline_macid.find(data['filterMAC']) != -1:
                    objs.append(o)
            else:
                objs.append(o)
            
    elif mode == 'disabled':
        for o in all.disabled():
            if params['filter_objects'].is_valid():
                data = params['filter_objects'].cleaned_data
                if data['PCNIdMin'] < o.targetid and data['PCNIdMax'] > o.targetid:
                    objs.append(o)
            elif params['filter_mac'].is_valid():
                data = params['filter_mac'].cleaned_data
                if o.caronline_macid.find(data['filterMAC']) != -1:
                    objs.append(o)
            else:
                objs.append(o)
            
    elif mode == 'normal':
        for o in all.normal():
            if params['filter_objects'].is_valid():
                data = params['filter_objects'].cleaned_data
                if data['PCNIdMin'] < o.targetid and data['PCNIdMax'] > o.targetid:
                    objs.append(o)
            elif params['filter_mac'].is_valid():
                data = params['filter_mac'].cleaned_data
                if o.caronline_macid.find(data['filterMAC']) != -1:
                    objs.append(o)
            else:
                objs.append(o)
            
    elif mode == 'test':
        for o in all.test():
            if params['filter_objects'].is_valid():
                data = params['filter_objects'].cleaned_data
                if data['PCNIdMin'] < o.targetid and data['PCNIdMax'] > o.targetid:
                    objs.append(o)
            elif params['filter_mac'].is_valid():
                data = params['filter_mac'].cleaned_data
                if o.caronline_macid.find(data['filterMAC']) != -1:
                    objs.append(o)
            else:
                objs.append(o)
            
    else:
        raise RuntimeError('задан некорректный режим(%s) работы' % (mode))
    params['objs'] = objs
    if not params['filter_objects'].is_valid():
        params['filter_objects'] = ObjectsFilterForm(initial={'PCNIdMin':0, 'PCNIdMax':999999})

def objectsList(request, mode):
    params = {}
    try:
        getObjects(request, mode, params)
        if params['filter_objects'].is_valid():
            conn = MSLib.CarOnlineDB(dbconfig).getconnection()
            cur = conn.cursor()
            
            for o in params['objs']:
                query = 'SELECT TOP(1) deviceId,eventTime,db,nc FROM _gsm_data_internal WHERE deviceId=%s ORDER BY eventTime DESC' % (str(o.msid))
                cur.execute(query)
                buf = cur.fetchall()
                o.gsm_signal = '0'
                o.gsm_operator = 'Unknown'
                try:
                    o.gsm_signal = str(buf[0][2])
                    opid = int(buf[0][3])
                    o.gsm_operator = {1:'MTS', 2:'Megafon'}.get(opid, str(opid))
                except:
                    pass
    except Exception, err:
        params['error'] = str(err)
    return render(request, 'safeinside/list_of_objects.html', params)

def objectsOnlineOffline(request, mode):
    params = {}
    try:
        standalone = False
        if mode == 'normal_standalone':
            standalone = True
            mode = 'normal'

        getObjects(request, mode, params)
        now = datetime.datetime.now()
        online = 0
        offline = 0
        for o in params['objs']:
            delta = now - o.lastEventTime
            delta = delta - datetime.timedelta(microseconds=delta.microseconds)
            o.delta = delta
            o.online = True
            o.ok = True
            if delta > datetime.timedelta(seconds=660):
                o.ok = False
            if delta > datetime.timedelta(seconds=3600*4):
                o.online = False
                offline += 1
            else:
                online += 1
            
        params['numonline'] = online
        params['numoffline'] = offline
        params['standalone'] = standalone
    except Exception, err:
        params['error'] = str(err)
    return render(request, 'safeinside/list_of_objects_simple.html', params)

def objectInfo(request, pcnid, login=None, msg=None):
    params = {}
    try:
        getObjects(request, 'all', params)
        params['obj'] = params['objs_all'].get(pcnid=pcnid, login=login)
        
        if msg is not None: params['message'] = msg
        
        init = {}
        init['objOldPCNId'] = params['obj'].targetid
        init['objOldLogin'] = params['obj'].caronline_login
        init['objOldMSId'] = params['obj'].msid
        init['objOldFirmware'] = params['obj'].versionSoftPGSM
        
        params['rename_object'] = ObjectRenameForm(request.POST)
        if not params['rename_object'].is_valid(): params['rename_object'] = ObjectRenameForm(initial=init)
        
        params['reload_firmware'] = ReloadFirmwareForm(request.POST)
        if not params['reload_firmware'].is_valid(): params['reload_firmware'] = ReloadFirmwareForm(initial=init)
        
    except Exception, err:
        params['error'] = str(err)
    return render(request, 'safeinside/info_object.html', params)

def objectCreate(request, mac=None):
    params = {}
    try:
        params['create_object'] = ObjectCreateForm(request.POST)
        if request.method == 'POST' and not params['create_object'].is_valid():
            raise RuntimeError('Введены некорректные данные. Исправьте, пожалуйста.')
            
        elif request.method == 'POST' and params['create_object'].is_valid():
            data = params['create_object'].cleaned_data
            if len(data['objMac']) > 0 and data['objPCNId'] > 0 \
                and data['objRegionSelected'] in ['car', 'dev']:
                login = data['objRegionSelected'] + str(data['objPCNId'])
                pwd = 'pass' + str(data['objPCNId'])
                done = MSLib.CarOnlineDB(dbconfig).objectCreate(data['objPCNId'], login, pwd, data['objMac'])
                msg = 'Объект успешно добавлен как %s' % str(done[3])
                
                newfirmware = None
                if data.has_key('objNewFirmwareSelected') and len(data['objNewFirmwareSelected']) > 0:
                    newfirmware = str(data['objNewFirmwareSelected'])
                if data.has_key('objNewFirmwareEntered') and len(data['objNewFirmwareEntered']) > 0:
                    newfirmware = str(data['objNewFirmwareEntered'])
                if newfirmware is not None:
                    MSLib.CarOnlineDB(dbconfig).objectReloadFirmware(done[2], newfirmware)
                    msg += ', инициирована перепрошивка на версию "%s"' % newfirmware
                return objectInfo(request, pcnid=int(done[0]), login=str(done[3]), msg=msg)
            raise RuntimeError('Введены некорректные данные. Исправьте, пожалуйста.')
            
        if mac is not None: params['create_object'] = ObjectCreateForm(initial={'objMac':mac})
    
    except Exception, err:
        params['error'] = str(err)
    return render(request, 'safeinside/object_create.html', params)

def objectRename(request):
    params = {}
    try:
        params['rename_object'] = ObjectRenameForm(request.POST)
        if request.method == 'POST' and params['rename_object'].is_valid():
            data = params['rename_object'].cleaned_data
            getObjects(request, 'all', params)
            obj = params['objs_all'].get(pcnid=data['objOldPCNId'], login=str(data['objOldLogin']))
            
            objNewPCNId = None
            objNewLogin = None
            try:
                if data.has_key('objNewPCNId') and data['objNewPCNId'] > 0 and data['objNewPCNId'] != data['objOldPCNId']:
                    objNewPCNId = data['objNewPCNId']
                    prefix = str(data['objOldLogin']).replace(str(data['objOldPCNId']), '')
                    objNewLogin = prefix + str(objNewPCNId)
                    
                elif data.has_key('objNewLogin') and len(data['objNewLogin']) > 0:
                    objNewLogin = str(data['objNewLogin'])
                    objNewPCNId = data['objOldPCNId']
                    
                MSLib.CarOnlineDB(dbconfig).objectRename(str(data['objOldLogin']), objNewLogin)
                    
            except:
                objNewLogin = None
                objNewPCNId = None
                
            msg = None
            if objNewLogin is not None and objNewPCNId:
                msg = 'Объект "%s" успешно переименован в "%s"' % (str(data['objOldLogin']), objNewLogin)
                return objectInfo(request, pcnid=objNewPCNId, login=objNewLogin, msg=msg)
            else:
                msg = 'Объект "%s" не переименован - данные введены неверно' % (str(data['objOldLogin']))
                return objectInfo(request, pcnid=data['objOldPCNId'], login=str(data['objOldLogin']), msg=msg)
                
    except Exception, err:
        params['error'] = str(err)
    return render(request, 'safeinside/hello.html', params)

def objectReloadFirmware(request):
    params = {}
    try:
        params['reload_firmware'] = ReloadFirmwareForm(request.POST)
        if request.method == 'POST' and params['reload_firmware'].is_valid():
            data = params['reload_firmware'].cleaned_data
            
            pcnid = data['objOldPCNId']
            login = str(data['objOldLogin'])
            msid = data['objOldMSId']
            oldfirmware = str(data['objOldFirmware'])
            
            newfirmware = None
            if data.has_key('objNewFirmwareSelected') and len(data['objNewFirmwareSelected']) > 0:
                newfirmware = str(data['objNewFirmwareSelected'])
            if data.has_key('objNewFirmwareEntered') and len(data['objNewFirmwareEntered']) > 0:
                newfirmware = str(data['objNewFirmwareEntered'])
            
            try:
                MSLib.CarOnlineDB(dbconfig).objectReloadFirmware(msid, newfirmware)
                msg = 'Для объекта "%s" успешно инициирована перепрошивка с версии "%s" на версию "%s"' % (login, oldfirmware, newfirmware)
            except Exception, err:
                msg = 'Для объекта "%s" не удалось инициировать перепрошивку с версии "%s" на версию "%s"' % (login, oldfirmware, newfirmware)
            
            return objectInfo(request, pcnid=pcnid, login=login, msg=msg)
                
    except Exception, err:
        params['error'] = str(err)
    return render(request, 'safeinside/hello.html', params)

def objectChangeState(request, pcnid, login):
    params = {}
    try:
        getObjects(request, 'all', params)
        obj = params['objs_all'].get(pcnid=pcnid, login=login)

        if obj.isTest:
            MSLib.Objects.makeNormal(config.get('main', 'normal_objects'), pcnid)
            obj.isTest = False
        else:
            MSLib.Objects.makeTest(config.get('main', 'normal_objects'), pcnid)
            obj.isTest = True
        params['obj'] = obj
        return objectInfo(request, pcnid=pcnid, login=login)

    except Exception, err:
        params['error'] = str(err)
    return render(request, 'safeinside/hello.html', params)
    
def oneObjectLogin(request):
    return render(request, 'safeinside/one_object_login.html', {'standalone':True})
def oneObject(request):
    params = {}
    getObjects(request, 'all', params)
    login   = request.REQUEST['objectLogin']
    pwd     = request.REQUEST['objectPassword']
    obj = None
    for o in params['objs_all'].all():
        if o.caronline_login == login and o.caronline_password == pwd:
            obj = o
    if obj != None:

        query1 = 'SELECT TOP(1) id,eventTime FROM _event_data_internal WHERE deviceId=%s ORDER BY eventTime DESC' % (str(obj.msid))
        query2 = 'SELECT TOP(1) id,eventTime,db,nc FROM _gsm_data_internal WHERE deviceId=%s ORDER BY eventTime DESC' % (str(obj.msid))

        conn = MSLib.CarOnlineDB(dbconfig).getconnection()
        cursor = conn.cursor()

        cursor.execute(query1)
        buf = cursor.fetchall()
        status = 'OFFLINE'
        if datetime.datetime.now() - buf[0][1] < datetime.timedelta(seconds=600):
            status = str(datetime.datetime.now() - buf[0][1]).split('.')[0]

        cursor.execute(query2)
        buf = cursor.fetchall()
        oper = {'1':'MTS', '2':'Megafon'}.get(str(buf[0][3]), 'N/A')
        signal = str(buf[0][2])

        params = \
        {
        'obj': obj,
        'status': status,
        'operator': oper,
        'standalone': True,
        'signal': signal,
        'error': False,
        }
    else:
        params = {'error' : True }
    return render(request, 'safeinside/one_object.html', params)


def getUnregisteredObjects(request):
    unregistered = MSLib.CarOnlineDB(dbconfig).objectsLoadUnregistered(config.get('main', 'not_registered_path'))
    params = {}
    getObjects(request, 'all', params)
    loaded_objects = params['objs_all'].objs

    for mac, entry in unregistered.iteritems():
        entry['hasRef'] = False
        if entry.has_key('msid') and (int(entry['msid']) in loaded_objects.keys()):
            entry['hasRef'] = True
            entry['ref'] = loaded_objects[int(entry['msid'])]
    params = \
    {
     'objs': unregistered,
    }
    return render(request, 'safeinside/unregistered_objects.html', params)

def objectsCountEventsByType(request, mode):
    standalone = False
    if mode == 'normal_standalone':
        standalone = True
    params = {}
    getObjects(request, 'all', params)
    loaded_objects = params['objs_all'].objs

    objs = {}
    db = MSLib.CarOnlineDB(dbconfig)
    for o in MSLib.Objects.iterateNormal(loaded_objects):
        counts = db.objectCountEventsByType(o.msid, None)
        o.counts = counts
        objs[int(o.targetid)] = o

    params = \
    {
     'objs':objs,
     'standalone':standalone,
    }
    return render(request, 'safeinside/objects_count_events_by_type.html', params)

def objectCountEventsByType(request, mode, pcnid):
    period = None
    standalone = False
    if mode == 'normal_standalone':
        standalone = True

    params = {}
    getObjects(request, 'all', params)
    loaded_objects = params['objs_all'].objs

    counts = MSLib.CarOnlineDB(dbconfig).objectCountEventsByType(obj.msid, period)
    obj.counts = counts

    params = \
    {
     'obj':obj,
     'standalone':standalone,
    }

    return render(request, 'safeinside/object_count_events_by_type.html', params)